<template>
  <view v-if="isCalendar" class="calendar_box">
    <view v-show="!isTime" class="btn_calendar_box">
      <view class="btn_box">
        <view class="cancel" @click="cancel">取消</view>
        <view class="tab_bar_box">
          <view class="tab_bar_item" :class="[calendarType === 'solar' ? 'activation_tab_bar' : '']"
                @click="tabBar('solar')">公历
          </view>
          <view class="tab_bar_item" :class="[calendarType === 'lunar' ? 'activation_tab_bar' : '']"
                @click="tabBar('lunar')">农历
          </view>
        </view>
        <view class="confirm" @click="confirm">确认</view>
      </view>

      <picker-view :indicator-style="indicatorStyle" :value="defaultValue" @change="bindChange"
                   style=" height: 400upx;">
        <picker-view-column>
          <view class="picker_item" v-for="item in years" :key="item.id">{{
              calendarType === 'solar' ?
                  item.$cytitle
                  : item.$gytitle
            }}
          </view>
        </picker-view-column>

        <picker-view-column>
          <view class="picker_item" v-for="item in months" :key="item.id">{{
              calendarType === 'solar' ?
                  item.$cmtitle
                  : item.IMonthCn
            }}
          </view>
        </picker-view-column>

        <picker-view-column>
          <view class="picker_item" v-for="item in days" :key="item.id">{{
              calendarType === 'solar' ?
                  item.$cdtitle
                  : item.IDayCn
            }}
          </view>
        </picker-view-column>

        <picker-view-column>
          <view class="picker_item" v-for="item in hours" :key="item.idh">{{ item.$lhou }}</view>
        </picker-view-column>
        <picker-view-column>
          <view class="picker_item" v-for="item in mins" :key="item.idm">{{ item.$lmin }}</view>
        </picker-view-column>
      </picker-view>
    </view>

    <view v-show="isTime" class="confirm_time_box">
      <view class="confirm_time_title">确认时间</view>
      <view class="input_time">请确认输入的时间是否正确</view>
      <view>
        <view class="value_box">
          公(阳)历：{{ confirmDate.lYear }}年{{ confirmDate.cMonth }}月{{ confirmDate.cDay }}日{{ hour.$lhou }}{{
            min.$lmin
          }}
        </view>
        <view class="value_box">
          农(阴)历：{{ confirmDate.gzYear }}年{{ confirmDate.IMonthCn }}{{ confirmDate.IDayCn }}{{ hour.$lhou }}{{
            min.$lmin
          }}
        </view>
      </view>

      <view class="back_correct_btn_box">
        <view class="back_edit" @click="backEdit">返回修改</view>
        <view class="correct" @click="alreadyCorrect">确认正确</view>
      </view>
    </view>
  </view>
</template>

<script>
// solar2lunar 阳转阴
// lunar2solar 阴转阳
import calendar from './js-calendar-converter/src/index';

export default {
  name: 'selectCalendar',
  data() {
    return {
      // lunar 阴历
      // solar 阳历
      calendarType: 'solar',
      defaultValue: [0, 0, 0, 0, 0],
      years: [],
      months: [],
      days: [],
      confirmDate: {},
      hours: [],
      hour: {},
      mins: [],
      min: {},
      indicatorStyle: undefined,
      dayIndex: 0,
      isTime: false,
      isCalendar: false
    }
  },

  methods: {
    // 确认正确
    alreadyCorrect() {
      document.body.removeEventListener('touchmove', this.preventDefault, {passive: false});
      let confirmDate = this.confirmDate,
          hour = this.hour,
          min = this.min,
          calendarType = this.calendarType,
          defaultValue = this.defaultValue,
          obj = {},
          resultStr = '';

      obj = Object.assign(confirmDate, hour, min);
      obj.calendarType = calendarType;
      obj.defaultValue = defaultValue;
      if (calendarType === 'solar') {
        resultStr = `${obj.$cytitle}${obj.$cmtitle}${obj.$cdtitle}`;
      } else {
        resultStr = `${obj.$gytitle}${obj.IMonthCn}${obj.IDayCn}`;
      }
      resultStr += `${obj.$lhou}${obj.$lmin}`;
      obj.result = resultStr;

      this.$emit('backData', {
        ...obj
      });

      this.isCalendar = false;
      this.isTime = false;
      this.calendarType = 'solar';
      this.confirmDate = {};
      this.defaultValue = [0, 0, 0, 0, 0];
      this.hour = {};
      this.min = {};
    },
    /**
     * 设置面板默认值/年月日时分
     * @author mj <1283077926@qq.com>
     * @license Apache-2.0
     * @param {Date} dateNow
     * @param {number} startYear
     * @param {number} endYear
     * @return {undefined} undefined
     */
    getTime(dateNow, startYear, endYear) {
      let years = [],
          year = dateNow.getFullYear(),
          months = [],
          month = dateNow.getMonth() + 1,
          days = [],
          day = dateNow.getDate(),
          hours = [],
          hour = dateNow.getHours() + 1,
          mins = [],
          min = dateNow.getMinutes(),
          indexOfF = (arr, IO) => arr.indexOf(IO),
          defaultValue = [];

      for (let i = startYear; i <= endYear; i++) years.push(i);
      for (let i = 0; i < 12; i++) months.push(i + 1);
      for (let i = 0; i < 31; i++) days.push(i + 1);
      for (let i = 0; i < 24; i++) hours.push(i);
      for (let i = 0; i < 60; i++) mins.push(i);

      defaultValue = [
        indexOfF(years, year),
        indexOfF(months, month),
        indexOfF(days, day),
        indexOfF(hours, hour),
        indexOfF(mins, min)
      ];

      this.defaultValue = defaultValue;
    },
    /**
     * 打开日期选择器
     * @author mj <1283077926@qq.com>
     * @license Apache-2.0
     * @param {Date} dateNow
     * @param {number} startYear
     * @param {number} endYear
     * @return {undefined} undefined
     */
    async openCalendar(info = {}, startYear, endYear) {
      document.body.addEventListener('touchmove', this.preventDefault, {passive: false});
      let dateNow = undefined;
      let nowYear = new Date().getFullYear();

      endYear = endYear < nowYear ? nowYear : endYear;

      if (!startYear) startYear = nowYear - 15;
      if (!endYear) endYear = nowYear + 5;
      startYear = startYear ? startYear : 1901;
      endYear = endYear ? endYear : (new Date()).getFullYear();

      startYear = startYear < 1901 ? 1901 : startYear;
      endYear = endYear > 2099 ? 2099 : endYear;
      if (Object.keys(info).length > 0) {
        this.calendarType = info.calendarType;
        this.confirmDate = info;
        this.defaultValue = [0, 0, 0, 0, 0];
        this.defaultValue = info.defaultValue;
        if (info.calendarType === 'solar') {
          dateNow = new Date(info.date);
        } else if (info.calendarType === 'lunar') {
          dateNow = new Date(info.lunarDate);
        } else {
          dateNow = new Date();
        }
      } else {
        this.calendarType = 'solar';
        this.confirmDate = {};
        this.defaultValue = [];
        dateNow = new Date();
        await this.getTime(dateNow, startYear, endYear);
      }
      this.indicatorStyle =
          await `height: ${Math.round(uni.getSystemInfoSync().screenWidth / (750 / 80))}px;`;
      await this.init(startYear, endYear);
      this.isCalendar = true;
    },
    preventDefault(event) {
      event.preventDefault();
    },
// 取消
    cancel() {
      document.body.removeEventListener('touchmove', this.preventDefault, {passive: false});
      this.isCalendar = false;
      this.calendarType = 'solar';
      this.confirmDate = {};
      this.defaultValue = [0, 0, 0, 0, 0];
      this.hour = {};
      this.min = {};
      this.$emit('backData', {});
    },
    // 返回修改
    backEdit() {
      this.isTime = false;
    },
    // 确认
    confirm() {
      let calendarType = this.calendarType,
          iVal = this.defaultValue,
          years = this.years,
          months = this.months,
          days = this.days,
          year = undefined,
          month = undefined,
          day = undefined,
          confirmDate = {},
          hours = this.hours,
          mins = this.mins;

      if (calendarType === 'solar') {
        year = years[iVal[0]].cYear;
        month = months[iVal[1]].cMonth;
        day = days[iVal[2]].cDay;

        confirmDate = calendar.solar2lunar(year, month, day);
      } else {
        year = years[iVal[0]].lYear;
        month = months[iVal[1]].lMonth;
        day = days[iVal[2]].lDay;

        confirmDate = calendar.lunar2solar(year, month, day, months[iVal[1]].isLeap);
      }

      confirmDate.id = 'idd' + parseInt(Math.random() * 10001, 10);
      confirmDate.$cytitle = confirmDate.cYear + '年';
      confirmDate.$gytitle = `${confirmDate.lYear}${confirmDate.gzYear}年`;
      confirmDate.$cmtitle = confirmDate.cMonth + '月';
      confirmDate.$cdtitle = confirmDate.cDay + '日';

      this.confirmDate = confirmDate;
      this.hour = hours[iVal[3]];
      this.min = mins[iVal[4]];
      this.isTime = true;
    },
    // 阴阳历转换选项卡二次数据处理
    async tabBarConfirm() {
      let calendarType = this.calendarType,
          iVal = this.defaultValue,
          nowDate = {},
          years = this.years,
          year = undefined,
          months = this.months,
          month = undefined,
          month1 = undefined,
          days = this.days,
          day = undefined,
          day1 = undefined,
          iny = 0,
          inm = 0,
          ind = 0;

      if (calendarType === 'solar') {
        year = years[iVal[0]].lYear;
        month1 = months[iVal[1]].lMonth;
        day1 = days[iVal[2]].lDay;

        nowDate = await calendar.lunar2solar(year, month1, day1, months[iVal[1]].isLeap);
      } else {
        year = years[iVal[0]].cYear;
        month1 = months[iVal[1]].cMonth;
        day1 = days[iVal[2]].cDay;

        nowDate = await calendar.solar2lunar(year, month1, day1);
      }

      let d = await this.getMonth(year);

      if (calendarType === 'solar') {
        iny = years.findIndex((item) => item.cYear === nowDate.cYear);
        inm = d.months.findIndex((item) => item.cMonth === nowDate.cMonth);
        ind = d.days.findIndex((item) => item.cDay === nowDate.cDay);
      } else {
        iny = years.findIndex((item) => item.lYear === nowDate.lYear);
        inm = d.months.findIndex((item) => item.IMonthCn === nowDate.IMonthCn);
        ind = d.days.findIndex((item) => item.lDay === nowDate.lDay);
      }

      if (calendarType === 'solar') {
        month = d.months[inm].cMonth;
        day = d.days[ind].cDay;

        nowDate = calendar.solar2lunar(year, month, day);
      } else {
        month = d.months[inm].lMonth;
        day = d.days[ind].lDay;

        nowDate = calendar.lunar2solar(year, month, day);
      }

      this.$set(this.defaultValue, 0, iny);
      this.$set(this.defaultValue, 1, inm);
      this.$set(this.defaultValue, 2, ind);

      this.$forceUpdate();
    },
    // 阴阳历转换选项卡
    tabBar(type) {
      if (type === this.calendarType) return false;

      this.calendarType = type;
      this.$nextTick(() => this.tabBarConfirm());
    },
    // 滑动触发
    async bindChange(event) {
      let val = event.detail.value,
          calendarType = this.calendarType,
          years = this.years,
          year = undefined;

      this.defaultValue[0] = val[0];
      this.defaultValue[1] = val[1];
      this.defaultValue[2] = val[2];
      this.defaultValue[3] = val[3];
      this.defaultValue[4] = val[4];

      year = years[val[0]][calendarType === 'solar' ? 'cYear' : 'lYear'];

      this.getMonth(year);
    },
    // 月份数据
    async getMonth(year) {
      let valArr = this.defaultValue,
          calendarType = this.calendarType,
          months = [],
          month = 1,
          isLeapMonth = calendar.leapMonth(year);

      if (calendarType === 'solar') {
        for (let i = 0; i < 12; i++) {
          let obj = calendar.solar2lunar(year, i + 1, 1);
          obj.id = 'idm' + i + 1;
          obj.$cmtitle = obj.cMonth + '月';

          months.push({
            ...obj
          });
        }
      } else {
        for (let i = 0; i < 12; i++) {
          let obj = {};

          if (isLeapMonth === i + 1) {
            obj = calendar.lunar2solar(year, i + 1, 1, false);
            obj.id = 'idm' + i + 1;
            months.push({
              ...obj
            });

            obj = calendar.lunar2solar(year, i + 1, 1, true);
            obj.id = 'idms' + i + 1;
            months.push({
              ...obj
            });
          } else {
            obj = calendar.lunar2solar(year, i + 1, 1, false);
            obj.id = 'idm' + i + 1;
            months.push({
              ...obj
            });
          }
        }
      }

      if (calendarType === 'solar') {
        month = months[valArr[1]].cMonth;
      } else {
        month = months[valArr[1]].lMonth;
      }

      // 根据年份和月份生成日期数据
      let days = await this.getDay(year, month);

      this.months = months;

      return {
        months,
        days
      };
    },
    // 日期
    getDay(year, month) {
      let calendarType = this.calendarType,
          days = [],
          day = this.defaultValue[2],
          daysLen = 0;

      if (calendarType === 'solar') {
        for (let j = 0; j < calendar.solarDays(year, month); j++) {
          let obj = calendar.solar2lunar(year, month, j + 1);

          days.push({
            ...obj
          });
        }
      } else {
        for (let j = 0; j < calendar.monthDays(year, month); j++) {
          let obj = calendar.lunar2solar(year, month, j + 1);

          days.push({
            ...obj
          });
        }
      }

      days = days.map((item, i) => {
        item.id = 'idd' + i;
        item.$cytitle = item.cYear + '年';
        item.$gytitle = `${item.lYear}${item.gzYear}年`;
        item.$cmtitle = item.cMonth + '月';
        item.$cdtitle = item.cDay + '日';

        return item;
      });

      daysLen = days.length - 1;
      day = day > daysLen ? daysLen : day;

      this.days = days;

      return days;
    },
    // 初始化
    async init(startYear, endYear) {
      let calendarType = this.calendarType,
          years = [],
          year = undefined,
          hoursArr = [],
          hours = [],
          mins = [],
          valArr = [],
          nowDate = {},
          Zhi = calendar.Zhi;

      for (let i = 0; i < Zhi.length; i++) {
        let item = Zhi[i];

        for (let j = 0; j < 2; j++) hoursArr.push(item);
      }

      hoursArr.push(hoursArr.splice(0, 1)[0]);
      hoursArr.unshift('未知时辰');
      hoursArr = hoursArr.splice(0);

      // 生成年份
      for (let i = startYear; i <= endYear; i++) {
        let obj = calendar.solar2lunar(i, 5, 1);
        obj.id = 'idy' + i;
        obj.$cytitle = obj.cYear + '年';
        obj.$gytitle = `${obj.lYear}${obj.gzYear}年`;

        years.push({
          ...obj
        });
      }

      if (this.confirmDate.defaultValue) {
        valArr = [...this.confirmDate.defaultValue];
      } else {
        valArr = [...this.defaultValue];
      }

      year = years[valArr[0]][calendarType === 'solar' ? 'cYear' : 'lYear'];

      // --------------------------
      // 根据年份获取月份
      await this.getMonth(year);

      // --------------------------
      // 时辰数据
      for (let i = 0; i < 25; i++) hours.push({
        idh: `id_${i + 1}`,
        $lhou: i !== 0 ? (i - 1) + hoursArr[i] : hoursArr[i],
        $chou: i - 1,
        $gzhou: hoursArr[i]
      });

      // 分钟数据
      for (let i = 0; i < 60; i++) mins.push({
        idm: `id_${i + 1}`,
        $lmin: i + '分',
        $cmin: i,
        $gzmin: ''
      });

      this.defaultValue = valArr;
      this.years = years;
      this.hours = hours;
      this.mins = mins;
      this.hour = this.hours[valArr[3]];
      this.min = this.mins[valArr[4]];
      this.nowDate = nowDate;
    }
  }
}
</script>

<style>
.calendar_box {
  position: fixed;
  left: 0;
  top: 0;
  width: 100vw;
  height: 100%;
  display: flex;
  flex-direction: column-reverse;
  background-color: rgba(0, 0, 0, 0.4);
  z-index: 6;
}

.btn_calendar_box {
  width: 100%;
  max-width: 640px;
  margin: 0 auto;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #ffffff;
  padding-top: 12upx;
  padding-bottom: 12upx;
  z-index: 7;
}

.btn_box {
  padding: 8upx 16upx;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.tab_bar_box {
  display: flex;
  justify-content: space-between;
  align-items: center;
  border: 1upx solid rgb(201, 23, 35);
  border-radius: 10upx;
}

.tab_bar_item {
  line-height: 40upx;
  padding: 10upx 30upx;
  color: rgb(201, 23, 35);
  cursor: pointer;
}

.activation_tab_bar {
  background: rgb(201, 23, 35);
  color: #FFFFFF;
}

.cancel {
  color: rgb(153, 153, 153);
  cursor: pointer;
  font-size: 32upx;
}

.confirm {
  color: rgb(201, 23, 35);
  cursor: pointer;
  font-size: 32upx;
}

.picker_item {
  line-height: 80upx;
  text-align: center;
  font-size: 28upx;
}

/* ------------------------------- */
.confirm_time_box {
  background-color: #ffffff;
  padding-top: 12upx;
  padding-bottom: 12upx;
  z-index: 7;
  width: 100%;
  max-width: 640px;
  margin: 0 auto;
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
}

.confirm_time_title {
  text-align: center;
  color: rgb(201, 23, 35);
  font-size: 32upx;
  border-bottom: 1upx solid #E8E8E8;
  height: 88upx;
  line-height: 88upx;
}

.input_time {
  text-align: center;
  font-size: 34upx;
  color: #000000;
  height: 48upx;
  line-height: 48upx;
  margin-top: 48upx;
  padding-bottom: 20upx;
}
.uni-picker-view-indicator{
  height: 40px!important;
}
.value_box {
  text-align: center;
  font-size: 34upx;
  color: rgb(163, 30, 26);
  height: 34upx;
  line-height: 34upx;
  padding: 10upx 0px;
}

.back_correct_btn_box {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 40upx 0;
  color: #ffffff;
}

.back_edit {
  padding: 20upx 40upx;
  border-radius: 10upx;
  background-color: #DDDDDD;
}

.correct {
  padding: 20upx 40upx;
  margin-left: 40upx;
  border-radius: 10upx;
  background-color: rgb(163, 30, 26);
}
</style>
